package cmpe.swe.purcom.controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import cmpe.swe.purcom.model.Community;
import cmpe.swe.purcom.model.Event;
import cmpe.swe.purcom.model.EventAttendance;
import cmpe.swe.purcom.model.FeedItem;
import cmpe.swe.purcom.model.Service;
import cmpe.swe.purcom.model.ServiceContribution;
import cmpe.swe.purcom.model.Stuff;
import cmpe.swe.purcom.model.StuffContribution;
import cmpe.swe.purcom.model.User;
import cmpe.swe.purcom.service.CommunityService;

@Controller
@RequestMapping("/community")
public class CommunityController {

	@Autowired
	private CommunityService communityService;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public ModelAndView listCommunities(Model model) {
		ModelAndView mv = new ModelAndView("communitysearch"); // TODO
		mv.addObject("communities", communityService.getCommunities());
		return mv;
	}

	/**
	 * Returns create community page for the logged in user. If user did not log
	 * in, returns the home page
	 * 
	 * @param model
	 *            object for spring form element
	 * @param command
	 *            Spring attribute for Community object
	 * @param ses
	 *            current server session
	 * @return create community page
	 */
	@RequestMapping(value = "/new", method = RequestMethod.GET)
	public String showCreateCommunity(Model model,
			@ModelAttribute("community") Object command, HttpSession ses) {
		User u = (User) ses.getAttribute("sessionUser");
		if (u == null) {
			return "redirect:/";
		}
		Community c = new Community();
		model.addAttribute("community", c);

		return "createcommunity";
	}

	/**
	 * Return a community page which is already created by a logged in user. If
	 * user did not log in, it returns the home page.
	 * 
	 * @param c
	 *            a Spring attribute for Community object
	 * @param req
	 *            a HttpServletRequest object is taken from the user
	 * @param ses
	 *            a HttpSession object which is current session information of
	 *            the user
	 * @return a community page
	 */
	@RequestMapping(value = "/new", method = RequestMethod.POST)
	public String createCommunity(@ModelAttribute("community") Community c,
			HttpServletRequest req, HttpSession ses) {
		String communityDateTime = req.getParameter("communityDateTime");
		Date date = null;
		try {
			date = new SimpleDateFormat("dd.mm.yyyy").parse(communityDateTime);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		c.setEnddate(date);
		User u = (User) ses.getAttribute("sessionUser");
		if (u == null) {
			return "redirect:/";
		}
		Community dbc = communityService.createCommunity(c, u.getId());
		return "redirect:" + dbc.getId() + "/";
	}

	/**
	 * Returns a community page with its property informations (stuff,event
	 * etc.) for logged in user. If user did not log in, it returns the home
	 * page
	 * 
	 * @param id
	 *            a Spring attribute for access switch
	 * @param session
	 *            a HttpSession object for current session of the user
	 * @return a community page
	 */
	@RequestMapping(value = "{id}/", method = RequestMethod.GET)
	public ModelAndView viewCommunity(@PathVariable("id") Long id,
			HttpSession session) {
		ModelAndView mv = new ModelAndView("communitydetail");
		Community c = communityService.getCommunity(id);
		if (c == null) {
			return new ModelAndView("redirect:/");
		}
		User u = (User) session.getAttribute("sessionUser");
		Long userId = u != null ? u.getId() : null;
		List<Service> se = communityService.getServices(id);
		List<Stuff> st = communityService.getStuffs(id);
		List<Event> e = communityService.getEvents(id);
		List<User> m = communityService.getCommunityMembers(id);
		List<FeedItem> fi = communityService.getActivityFeedOfCommunity(id);
		Map<String, Object> mship = communityService.getMembership(id, userId);
		mv.addObject("stuffs", st);
		mv.addObject("services", se);
		mv.addObject("events", e);
		mv.addObject("community", c);
		mv.addObject("members", m);
		mv.addObject("membership", mship);
		mv.addObject("feedItems", fi);
		return mv;
	}

	/**
	 * Returns a community page with the given name.
	 * 
	 * @param name
	 *            name property for the search process
	 * @return a community page
	 */
	@RequestMapping(value = "/search", method = RequestMethod.POST)
	public ModelAndView searchCommunity(@RequestParam("name") String name) {
		ModelAndView mv = new ModelAndView("communitysearch");
		List<Community> communities = communityService
				.searchCommunitiesByName(name);
		mv.addObject("communities", communities);
		return mv;
	}

	/**
	 * Returns a community page which is already joined for the logged in user.
	 * If user did not log in it returns the home page
	 * 
	 * @param communityId
	 *            a Spring attribute for access switch
	 * @param session
	 *            a HttpSession object for the current session of the user
	 * @return a community page
	 */
	@RequestMapping(value = "/{id}/join", method = RequestMethod.POST)
	public @ResponseBody
	boolean joinCommunity(@PathVariable("id") Long communityId,
			HttpSession session) {
		User u = (User) session.getAttribute("sessionUser");
		if (u != null) {
			communityService.joinCommunity(communityId, u.getId());
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 
	 * @param communityId
	 *            a Spring attribute for access switch
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user
	 * @return
	 */
	@RequestMapping(value = "/{id}/leave", method = RequestMethod.POST)
	public @ResponseBody
	boolean leaveCommunity(@PathVariable("id") Long communityId,
			HttpSession session) {
		User u = (User) session.getAttribute("sessionUser");
		if (u != null) {
			communityService.leaveCommunity(communityId, u.getId());
			return true;
		} else {
			return false;
		}
	}

	/*
	 * STUFF methods
	 */

	/**
	 * Returns a stuff page which is already created by the logged in user. If
	 * user did not log in it returns null.
	 * 
	 * @param s
	 *            a Spring attribute for Stuff object
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user
	 * @return a Stuff page
	 */
	@RequestMapping(value = "/{id}/stuff/new", method = RequestMethod.POST)
	public @ResponseBody
	Stuff createStuff(@RequestBody Stuff s, HttpSession session) {
		if (s.getAmountContributed() == null || s.getAmountRequested() == null
				|| s.getName() == null || s.getName().equals("")
				|| s.getDescription() == null || s.getDescription().equals("")
				|| s.getLocation().equals("")) {
			return null;
		}
		User u = (User) session.getAttribute("sessionUser");
		if (u == null) {
			return null;
		}
		return communityService.createStuff(s, u.getId());
	}

	/**
	 * Returns a stuff page with its property information for the logged in
	 * user. If user did not log in it returns the community home page
	 * 
	 * @param communityId
	 *            a Spring attribute for access switch
	 * @param stuffId
	 *            a Spring attribute for access switch
	 * @return a stuff page
	 */
	@RequestMapping(value = "/{id}/stuff/{stuffId}/", method = RequestMethod.GET)
	public ModelAndView viewStuff(@PathVariable("id") Long communityId,
			@PathVariable("stuffId") Long stuffId, HttpSession session) {
		User u = (User) session.getAttribute("sessionUser");
		ModelAndView v = new ModelAndView("stuffdetail");
		Stuff s = communityService.getStuff(communityId, stuffId);
		Community c = communityService.getCommunity(communityId);
		if (s == null) {
			return new ModelAndView("redirect:/community/" + communityId);
		}
		List<StuffContribution> fi = communityService.getActivityFeedOfStuff(stuffId);
		v.addObject("feedItems", fi);
		v.addObject("stuff", s);
		v.addObject("community", c);
		if (u != null) {
			v.addObject("membership",
					communityService.getMembership(c.getId(), u.getId()));
		}
		return v;
	}

	/**
	 * Adds the contribution of the user to the stuff
	 * 
	 * @param stuffId
	 *            Id of stuff to which is contributed
	 * @param sc
	 *            Contribution object
	 * @param session
	 * @return Contribution object added
	 */
	@RequestMapping(value = "/{id}/stuff/{stuffId}/contribute", method = RequestMethod.POST)
	public @ResponseBody
	StuffContribution contributeStuff(@PathVariable("stuffId") Long stuffId,
			@RequestBody StuffContribution sc, HttpSession session) {
		User u = (User) session.getAttribute("sessionUser");
		if (u == null) {
			return null;
		}
		sc.setUserID(u.getId());
		return communityService.contributeToStuff(sc);
	}

	/*
	 * EVENT methods
	 */

	/**
	 * Returns an event page which is already created for the logged in user. If
	 * user did not log in it returns null
	 * 
	 * @param e
	 *            a Spring attribute for Event object
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user
	 * @return an event page
	 */
	@RequestMapping(value = "/{id}/event/new", method = RequestMethod.POST)
	public @ResponseBody
	Event createEvent(@RequestBody Event e, HttpSession session) {
		User u = (User) session.getAttribute("sessionUser");
		if (u == null) {
			return null;
		}
		return communityService.createEvent(e, u.getId());
	}

	/**
	 * Returns an event page with its property information for the logged in
	 * user. If user did not log in it returns the community home page
	 * 
	 * @param communityId
	 *            a Spring attribute for access switch
	 * @param eventId
	 *            a Spring attribute for access switch
	 * @return an event page
	 */
	@RequestMapping(value = "/{id}/event/{eventId}/", method = RequestMethod.GET)
	public ModelAndView viewEvent(@PathVariable("id") Long communityId,
			@PathVariable("eventId") Long eventId) {
		ModelAndView v = new ModelAndView("eventdetail");
		Event s = communityService.getEvent(communityId, eventId);
		Community c = communityService.getCommunity(communityId);
		if (s == null) {
			return new ModelAndView("redirect:/community/" + communityId);
		}
		
		List<EventAttendance> fi = communityService.getActivityFeedOfEvent(eventId);
		v.addObject("feedItems", fi);
		v.addObject("event", s);
		v.addObject("community", c);
		return v;
	}

	/*
	 * SERVICE methods
	 */

	/**
	 * * Returns a service page which is already created for the logged in user.
	 * If user did not log in it returns null
	 * 
	 * @param s
	 *            a Spring attribute for Service object
	 * @param session
	 *            a HttpSession object for the current session information of
	 *            the user
	 * @return a service page
	 */
	@RequestMapping(value = "/{id}/service/new", method = RequestMethod.POST)
	public @ResponseBody
	Service createService(@RequestBody Service s, HttpSession session) {
		User u = (User) session.getAttribute("sessionUser");
		if (u == null) {
			return null;
		}
		return communityService.createService(s, u.getId());
	}

	/**
	 * Returns a service page with its property information for the logged in
	 * user. If user did not log in it returns the community home page
	 * 
	 * @param communityId
	 *            a Spring attribute for access switch
	 * @param serviceId
	 *            a Spring attribute for access switch
	 * @return a service page
	 */
	@RequestMapping(value = "/{id}/service/{serviceId}/", method = RequestMethod.GET)
	public ModelAndView viewService(@PathVariable("id") Long communityId,
			@PathVariable("serviceId") Long serviceId) {
		ModelAndView v = new ModelAndView("servicedetail");
		Service s = communityService.getService(communityId, serviceId);
		Community c = communityService.getCommunity(communityId);
		if (s == null) {
			return new ModelAndView("redirect:/community/" + communityId);
		}
		List<ServiceContribution> fi = communityService.getActivityFeedOfService(serviceId);
		v.addObject("feedItems", fi);
		v.addObject("service", s);
		v.addObject("community", c);
		return v;
	}

	/**
	 * Adds the contribution of the user to the service
	 * 
	 * @param serviceId
	 *            Id of service to which is contributed
	 * @param sc
	 *            Contribution object
	 * @param session
	 * @return Contribution object added
	 */
	@RequestMapping(value = "/{id}/service/{serviceId}/contribute", method = RequestMethod.POST)
	public @ResponseBody
	ServiceContribution contributeService(
			@PathVariable("serviceId") Long serviceId,
			@RequestBody ServiceContribution sc, HttpSession session) {
		User u = (User) session.getAttribute("sessionUser");
		if (u == null) {
			return null;
		}
		sc.setUserID(u.getId());
		return communityService.contributeToService(sc);
	}
	

}
